import 'package:flutter/material.dart';
import 'package:example/base/custom_widget.dart';
import 'package:example/utils/common.dart';
import 'package:example/config/color_config.dart';
import 'package:example/widget/my_image.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';

typedef TabSelected = Function(int index);

class BottomNavigationView extends CustomWidget<NavigationTabController> {
  final double height;
  final Color background;
  final Color pageBackground;

  final Size iconSize;
  final Size iconSelectedSize;
  final double textPadding;
  final Color textColor;
  final Color textSelectedColor;
  final double textSize;
  final double textSelectedSize;
  final FontWeight textWeight;
  final FontWeight textSelectedWeight;
  final TabSelected? tabSelected;

  final List<NavigationTab> _tabs = [];

  BottomNavigationView({
    Key? key,
    List<Widget>? pages,
    NavigationTabController? controller,
    int currentIndex = 0,
    List<String> titles = const [],
    List<String> iconList = const [],
    List<String> iconSelectedList = const [],
    this.height = 48,
    this.background = Colors.white,
    this.pageBackground = Colors.transparent,
    this.iconSize = const Size(28, 28),
    this.iconSelectedSize = const Size(28, 28),
    this.textPadding = 4,
    this.textColor = Colors.black,
    this.textSelectedColor = Colors.black,
    this.textSize = 10,
    this.textSelectedSize = 10,
    this.textWeight = FontWeight.normal,
    this.textSelectedWeight = FontWeight.normal,
    this.tabSelected,
  }) : super(
            _defaultController(
                currentIndex, pages, titles, iconList, iconSelectedList),
            key: key,
            externalController: controller) {
    assert(pages == null || pages.length == initController.titles.length,
        "pages.length与controller-> titles.length长度不一致");
    assert(pages == null || pages.length == initController.iconList.length,
        "pages.length与controller-> iconList.length长度不一致");
  }

  @override
  Widget initView(BuildContext context, NavigationTabController controller) {
    return Stack(
      children: [
        Positioned(
          left: 0,
          top: 0,
          right: 0,
          bottom: 0,
          child: Container(
            color: pageBackground,
            padding: EdgeInsets.only(
              bottom: height + ScreenUtil().bottomBarHeight,
            ),
            child: PageView(
              controller: controller.pageController,
              children: controller.pages ?? [],
              physics: const NeverScrollableScrollPhysics(),
            ),
          ),
        ),
        Positioned(
          bottom: 0,
          left: 0,
          right: 0,
          child: _tabLayout(context, controller),
        ),
      ],
    );
  }

  _tabLayout(BuildContext context, NavigationTabController controller) {
    return GetBuilder<NavigationTabController>(
      id: controller.idTabLayout,
      init: controller,
      global: false,
      builder: (controller) {
        _tabs.clear();
        for (int i = 0; i < controller.titles.length; i++) {
          _tabs.add(
            NavigationTab(
              id: i,
              controller: controller,
              textPadding: textPadding,
              iconSize: iconSize,
              iconSelectedSize: iconSelectedSize,
              textColor: textColor,
              textSelectedColor: textSelectedColor,
              textSize: textSize,
              textSelectedSize: textSelectedSize,
              textWeight: textWeight,
              textSelectedWeight: textSelectedWeight,
              tabSelected: tabSelected,
            ),
          );
        }
        return Container(
          height: height + ScreenUtil().bottomBarHeight,
          padding: EdgeInsets.only(bottom: ScreenUtil().bottomBarHeight),
          decoration: BoxDecoration(
            color: background,
            borderRadius: BorderRadius.vertical(top: Radius.circular(14.r)),
            boxShadow: [
              BoxShadow(
                color: ColorConfig.FF151622.withOpacity(0.04),
                blurRadius: 5.r,
                offset: Offset(0, -3.w),
              ),
            ],
          ),
          width: double.infinity,
          child: Row(
            children: _tabs,
          ),
        );
      },
    );
  }

  static NavigationTabController _defaultController(
      int currentIndex,
      List<Widget>? pages,
      List<String> titles,
      List<String> iconList,
      List<String> iconSelectedList) {
    NavigationTabController controller = NavigationTabController(
      pages: pages,
      titles: titles,
      iconList: iconList,
      iconSelectedList: iconSelectedList,
      currentIndex: currentIndex,
    );
    return controller;
  }
}

class NavigationTab extends StatefulWidget {
  final NavigationTabController controller;
  final int id;
  final Size iconSize;
  final Size iconSelectedSize;
  final double textPadding;
  final Color textColor;
  final Color textSelectedColor;
  final double textSize;
  final double textSelectedSize;
  final FontWeight textWeight;
  final FontWeight textSelectedWeight;
  final TabSelected? tabSelected;

  const NavigationTab({
    required this.id,
    required this.controller,
    Key? key,
    this.textPadding = 4,
    this.iconSize = const Size(28, 28),
    this.iconSelectedSize = const Size(28, 28),
    this.textColor = Colors.black,
    this.textSelectedColor = Colors.black,
    this.textSize = 10,
    this.textSelectedSize = 10,
    this.textWeight = FontWeight.normal,
    this.textSelectedWeight = FontWeight.normal,
    this.tabSelected,
  }) : super(key: key);

  @override
  State<NavigationTab> createState() => _NavigationTabState();
}

class _NavigationTabState extends State<NavigationTab>
    with SingleTickerProviderStateMixin {
  AnimationController? animController;

  @override
  void initState() {
    super.initState();
    animController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300),
    );
    animController?.reset();
  }

  @override
  void dispose() {
    animController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GetBuilder<NavigationTabController>(
        id: widget.id,
        init: widget.controller,
        global: false,
        builder: (controller) {
          String icon = controller.getIcon(widget.id);
          if (controller.isSelected(widget.id)) {
            animController?.animateTo(1);
          } else {
            animController?.reset();
          }
          return Expanded(
            child: GestureDetector(
              onTap: () {
                if (!controller.isSelected(widget.id)) {
                  controller.setSelected(widget.id);
                  widget.tabSelected?.call(widget.id);
                } else {
                  //回到顶部
                  _handleStatusBarTap(context);
                }
              },
              child: Container(
                height: double.infinity,
                width: double.infinity,
                color: Colors.transparent,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    isEmptyOrNull(icon)
                        ? SizedBox(
                            width: controller.isSelected(widget.id)
                                ? (widget.iconSelectedSize.width == 0
                                    ? null
                                    : widget.iconSelectedSize.width)
                                : (widget.iconSize.width == 0
                                    ? null
                                    : widget.iconSize.width),
                            height: controller.isSelected(widget.id)
                                ? (widget.iconSelectedSize.height == 0
                                    ? null
                                    : widget.iconSelectedSize.height)
                                : (widget.iconSize.height == 0
                                    ? null
                                    : widget.iconSize.height),
                          )
                        : MyImage(
                            path: icon,
                            controller: animController,
                            animate: controller.isSelected(widget.id),
                            // color: controller.getIcon(id),
                            width: controller.isSelected(widget.id)
                                ? (widget.iconSelectedSize.width == 0
                                    ? null
                                    : widget.iconSelectedSize.width)
                                : (widget.iconSize.width == 0
                                    ? null
                                    : widget.iconSize.width),
                            height: controller.isSelected(widget.id)
                                ? (widget.iconSelectedSize.height == 0
                                    ? null
                                    : widget.iconSelectedSize.height)
                                : (widget.iconSize.height == 0
                                    ? null
                                    : widget.iconSize.height),
                          ),
                    SizedBox(height: widget.textPadding),
                    Text(
                      controller.getTitle(widget.id),
                      overflow: TextOverflow.ellipsis,
                      style: TextStyle(
                        color: controller.isSelected(widget.id)
                            ? widget.textSelectedColor
                            : widget.textColor,
                        fontSize: controller.isSelected(widget.id)
                            ? widget.textSelectedSize
                            : widget.textSize,
                        fontWeight: controller.isSelected(widget.id)
                            ? widget.textSelectedWeight
                            : widget.textWeight,
                      ),
                    )
                  ],
                ),
              ),
            ),
          );
        });
  }

  void _handleStatusBarTap(context) {
    final ScrollController primaryScrollController =
        PrimaryScrollController.of(context);
    if (primaryScrollController.hasClients) {
      primaryScrollController.animateTo(
        0.0,
        duration: const Duration(milliseconds: 300),
        curve: Curves.linear,
      );
    }
  }
}

class NavigationTabController extends GetxController {
  final String idTabLayout = "idTabLayout";
  final PageController pageController = PageController();
  List<Widget>? pages;
  final List<String> titles;
  final List<String> iconList;
  final List<String> iconSelectedList;
  int currentIndex;

  NavigationTabController(
      {this.pages,
      required this.titles,
      required this.iconList,
      required this.iconSelectedList,
      this.currentIndex = 0}) {
    assert(pages == null || pages!.length == titles.length,
        "pages.length与controller-> titles.length长度不一致");
    assert(pages == null || pages!.length == iconList.length,
        "pages.length与controller-> iconList.length长度不一致");
  }

  setSelected(int index) {
    int oldIndex = currentIndex;
    currentIndex = index;
    pageController.jumpToPage(currentIndex);
    update([index, oldIndex]);
  }

  bool isSelected(int index) {
    return currentIndex == index;
  }

  String getIcon(int index) {
    if (iconList.isEmpty || iconList.length <= index) return "";
    bool selectedIcon =
        iconSelectedList.isNotEmpty && iconSelectedList.length > index;
    if (isSelected(index) && selectedIcon) {
      return iconSelectedList[index];
    } else {
      return iconList[index];
    }
  }

  String getTitle(int index) {
    if (titles.isEmpty || titles.length <= index) return "";
    return titles[index];
  }

  void setMenu(List<Widget> pages, List<String> titles, List<String> iconList,
      List<String> iconSelectedList) {
    assert(pages.length == titles.length,
        "pages.length与controller-> titles.length长度不一致");
    assert(pages.length == iconList.length,
        "pages.length与controller-> iconList.length长度不一致");

    this.titles.clear();
    this.iconList.clear();
    this.iconSelectedList.clear();

    this.pages = pages;
    this.titles.addAll(titles);
    this.iconList.addAll(iconList);
    this.iconSelectedList.addAll(iconSelectedList);

    if (currentIndex >= titles.length) {
      setSelected(0);
    }
    update();
  }

  Widget? getCurrentPage() {
    if (currentIndex >= (pages?.length ?? 0)) {
      return const SizedBox();
    }
    return pages?[currentIndex];
  }
}
